﻿using System;
using ProtoBuf;

namespace Test
{
    /// <summary>
    /// 房态(RoomInfo)
    /// </summary>
    [ProtoContract]
    [Serializable]
    public class RoomInfoV3
    {
        private const uint Mask = 0xFFFFFFFF;

        [ProtoMember(19, IsRequired = true)]
        public uint InternalData = Mask;
        /// <summary>
        /// 推荐级别 0-3
        /// </summary>
        public byte Recommend
        {
            get { return (byte)(InternalData & 15); }
            set
            {
                InternalData &= (uint)(~15 | value);
            }
        }

        /// <summary>
        /// 房态 4-6
        /// </summary>
        public string RoomStatus
        {
            get
            {
                var data = (InternalData >> 4) & 7;
                switch (data)
                {
                    default:
                    case 0:
                        return "N";
                    case 1:
                        return "G";
                    case 2:
                        return "L";
                    case 3:
                        return "U";
                    case 4:
                        return "S";
                }
            }
            set
            {

                uint data;
                switch (value)
                {
                    default:
                    case "N":
                        data = 0;
                        break;
                    case "G":
                        data = 1;
                        break;
                    case "L":
                        data = 2;
                        break;
                    case "U":
                        data = 3;
                        break;
                    case "S":
                        data = 4;
                        break;
                }
                InternalData = InternalData & (~(7u << 4)) | (data << 4);
            }
        }

        /// <summary>
        /// 是否有大床 8-9
        /// </summary>
        public string HasKingSize
        {
            get
            {
                var data = (InternalData >> 7) & 3;
                switch (data)
                {
                    default:
                    case 0:
                        return " ";
                    case 1:
                        return "T";
                    case 2:
                        return "F";
                    case 3:
                        return "U";
                }
            }
            set
            {

                uint data;
                switch (value)
                {
                    default:
                    case " ":
                        data = 0;
                        break;
                    case "T":
                        data = 1;
                        break;
                    case "F":
                        data = 2;
                        break;
                    case "U":
                        data = 3;
                        break;
                }
                InternalData = InternalData & (~(3u << 7)) | (data << 7);
            }
        }

        /// <summary>
        /// 是否有双床 17
        /// </summary>
        public string HasTwinBed
        {
            get
            {
                var data = (InternalData >> 16) & 3;
                switch (data)
                {
                    default:
                    case 0:
                        return " ";
                    case 1:
                        return "T";
                    case 2:
                        return "F";
                }
            }
            set
            {

                uint data;
                switch (value)
                {
                    default:
                    case " ":
                        data = 0;
                        break;
                    case "T":
                        data = 1;
                        break;
                    case "F":
                        data = 2;
                        break;
                }
                InternalData = InternalData & (~(3u << 16)) | (data << 16);
            }
        }

        /// <summary>
        /// 担保 10-11
        /// </summary>
        public string Allneedguarantee
        {
            get
            {
                var data = (InternalData >> 9) & 3;
                switch (data)
                {
                    default:
                    case 0:
                        return "F";
                    case 1:
                        return "B";
                    case 2:
                        return "T";
                }
            }
            set
            {

                uint data;
                switch (value)
                {
                    default:
                    case "F":
                        data = 0;
                        break;
                    case "B":
                        data = 1;
                        break;
                    case "T":
                        data = 2;
                        break;
                }
                InternalData = InternalData & (~(3u << 9)) | (data << 9);
            }
        }

        /// <summary>
        /// 用户限制
        /// </summary>
        [ProtoMember(9)]
        public short Userlimited;

        /// <summary>
        /// 保留房最晚预定时间(offline使用的)
        /// </summary>
        [ProtoMember(10)]
        public short HoldReserveTime;

        /// <summary>
        /// 预付扣款方式 12
        /// </summary>
        public string DeductType
        {
            get { return ((InternalData >> 11) & 1) > 0 ? "C" : "F"; }
            set
            {
                var data = 1 << 11;
                if (value == "C")
                {
                    InternalData |= (uint)data;
                }
                else
                {
                    InternalData &= (uint)~data;
                }
            }
        }

        /// <summary>
        /// FreeSale 13
        /// </summary>
        public string FreeSale
        {
            get { return ((InternalData >> 12) & 1) > 0 ? "T" : "F"; }
            set
            {
                var data = 1 << 12;
                if (value == "T")
                {
                    InternalData |= (uint)data;
                }
                else
                {
                    InternalData &= (uint)~data;
                }
            }
        }

        /// <summary>
        /// HoldDeadline,超时担保时间,格式为 小时*100+分钟,例如:2030表示20点30分
        /// </summary>
        [ProtoMember(13)]
        public short HoldDeadline;

        /// <summary>
        /// 最晚预定时间(int)
        /// </summary>
        [ProtoMember(14)]
        public short ReserveTime;

        /// <summary>
        /// 房型最晚取消时间(小时数)
        /// </summary>
        [ProtoMember(15)]
        public short Prepaylct;

        /// <summary>
        /// C:行用卡担保,M:手机担保 14
        /// </summary>
        public string GuaranteeType
        {
            get { return ((InternalData >> 13) & 1) > 0 ? "C" : "M"; }
            set
            {
                var data = 1 << 13;
                if (value == "C")
                {
                    InternalData |= (uint)data;
                }
                else
                {
                    InternalData &= (uint)~data;
                }
            }
        }

        /// <summary>
        /// 担保房型最晚取消时间(小时数)
        /// </summary>
        [ProtoMember(17)]
        public short Guaranteelct;

        /// <summary>
        /// 检查类型(住店,到店统计) 15
        /// </summary>
        public string CheckType
        {
            get { return ((InternalData >> 14) & 1) > 0 ? "C" : "S"; }
            set
            {
                var data = 1 << 14;
                if (value == "C")
                {
                    InternalData |= (uint)data;
                }
                else
                {
                    InternalData &= (uint)~data;
                }
            }
        }

        /// <summary>
        /// 最晚预定时间是否有效 16
        /// </summary>
        public string ReserveTimeFlag
        {
            get { return ((InternalData >> 15) & 1) > 0 ? "T" : "F"; }
            set
            {
                var data = 1 << 15;
                if (value == "T")
                {
                    InternalData |= (uint)data;
                }
                else
                {
                    InternalData &= (uint)~data;
                }
            }
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            RoomInfoV3 roomInfoV3 = obj as RoomInfoV3;
            if (roomInfoV3 == null)
            {
                return false;
            }
            return InternalData == roomInfoV3.InternalData
                   && Userlimited == roomInfoV3.Userlimited
                   && HoldReserveTime == roomInfoV3.HoldReserveTime
                   && HoldDeadline == roomInfoV3.HoldDeadline
                   && ReserveTime == roomInfoV3.ReserveTime
                   && Prepaylct == roomInfoV3.Prepaylct
                   && Guaranteelct == roomInfoV3.Guaranteelct;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hash = (int)InternalData;
                hash = hash * 23 + Userlimited;
                hash = hash * 23 + HoldReserveTime;
                hash = hash * 23 + HoldDeadline;
                hash = hash * 23 + ReserveTime;
                hash = hash * 23 + Prepaylct;
                hash = hash * 23 + Guaranteelct;
                return hash;
            }
        }

        public RoomInfoV3 Clone()
        {
            var ri = new RoomInfoV3();
            ri.InternalData = InternalData;
            ri.Userlimited = Userlimited;
            ri.HoldReserveTime = HoldReserveTime;
            ri.HoldDeadline = HoldDeadline;
            ri.ReserveTime = ReserveTime;
            ri.Prepaylct = Prepaylct;
            ri.Guaranteelct = Guaranteelct;
            return ri;
        } 
    }
}
